#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //auto selectTime1 = new selectTime(this);
    auto selectTime1 = new RollingBox(this);
    selectTime1->resize(200, 100);
}

Widget::~Widget()
{
    delete ui;
}


RollingBox::RollingBox(QWidget *parent) :
    QWidget(parent),m_minRange(0),m_maxRange(10),
    m_rangeSpan(m_maxRange-m_minRange+1),
    m_currentValue(5),isDragging(0),m_deviation(0),m_numSize(6)
{
    homingAni  = new QPropertyAnimation(this,"deviation");//动画用于将选中数字归到中间位置
    homingAni->setDuration(300);
    homingAni->setEasingCurve(QEasingCurve::OutQuad);
}

void RollingBox::setRange(int min,int max)
{
    m_minRange = min;
    m_maxRange = max;
    m_rangeSpan = m_maxRange - m_minRange + 1;

    if(m_currentValue < min)
        m_currentValue = min;
    if(m_currentValue > max)
        m_currentValue = max;

    //计算字符尺寸
    m_numSize = 3;
    int temp = m_maxRange;
    while(temp > 0)
    {
        temp /= 10;
        m_numSize++;
    }

    repaint();
}

int RollingBox::readValue()
{
    return m_currentValue;
}

void RollingBox::mousePressEvent(QMouseEvent *e)
{
    homingAni->stop();
    isDragging = 1;
    m_mouseSrcPos = e->pos().x();
}

void RollingBox::mouseMoveEvent(QMouseEvent *e)
{
    if(isDragging)
    {
        //数值到边界时，阻止继续往对应方向移动
//        if((m_currentValue == m_minRange && e->pos().x() >= m_mouseSrcPos)||
//          (m_currentValue == m_maxRange && e->pos().x() <= m_mouseSrcPos))
//            return;

        m_deviation = e->pos().x() - m_mouseSrcPos;

        //若移动速度过快时进行限制
        if(m_deviation > (width()-1)/4)
            m_deviation = (width()-1)/4;
        else if(m_deviation < -(width()-1)/4)
            m_deviation = -(width()-1)/4;

        emit deviationChange((float)m_deviation/((width()-1)/4));

        repaint();
    }
}

void RollingBox::mouseReleaseEvent(QMouseEvent *)
{
    if(isDragging)
    {
        isDragging = 0;
        homing();
    }
}

void RollingBox::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    int Width = width()-1;
    int Height = height()-1;

    //计算当前中心数字，及位置
    if(m_deviation >= Width/4)
    {
        m_mouseSrcPos += Width/4;
        m_deviation -= Width/4;
        m_currentValue -= 1;
    }
    if(m_deviation <= -Width/4)
    {
        m_mouseSrcPos -= Width/4;
        m_deviation += Width/4;
        m_currentValue += 1;
    }

    //中间数字
    paintNum(painter,calculateLoopNum(m_currentValue),m_deviation);

    //两侧数字1
    paintNum(painter,calculateLoopNum(m_currentValue-1),m_deviation-Width/4);
    paintNum(painter,calculateLoopNum(m_currentValue+1),m_deviation+Width/4);

    //两侧数字2
    if(m_deviation >= 0)
        paintNum(painter,calculateLoopNum(m_currentValue-2),m_deviation-Width/2);
    if(m_deviation <= 0)
        paintNum(painter,calculateLoopNum(m_currentValue+2),m_deviation+Width/2);

    //边框
    painter.setPen(QPen(QColor(0,0,0,120),2));
    painter.drawLine(Width/8*3,0,Width/8*3,Height);
    painter.drawLine(Width/8*5,0,Width/8*5,Height);
}

void RollingBox::wheelEvent(QWheelEvent *event)
{
    //qDebug() << event->angleDelta();
    m_deviation =  width() / 8 + 1;
    if (event->angleDelta().y() > 0)
        m_deviation = 0 - m_deviation;

    homing();
}

void RollingBox::paintNum(QPainter &painter,int num,int deviation)
{
    int Width = width()-1;
    int Height = height()-1;

    int size = (Width - qAbs(deviation))/m_numSize;//字体大小，距离中心越远越小
    int transparency = 255-510*qAbs(deviation)/Width;//字体透明度，距离中心越远越透明
    int width = Width/2-3*qAbs(deviation)/4;//数字宽度，距离中心越远越小
    int x = Width/2+deviation-width/2;//数字左边界

    QFont font;
    font.setPixelSize(size);
    painter.setFont(font);
    painter.setPen(QColor(0,0,0,transparency));
    painter.drawText(QRectF(x,0,width,Height),
                     Qt::AlignCenter,
                     QString::number(num));
}

void RollingBox::homing()
{
    //将数字矫正到中心
    if(m_deviation > width()/8)
    {
        homingAni->setStartValue((width()-1)/8-m_deviation);
        homingAni->setEndValue(0);
        m_currentValue--;
    }
    else if(m_deviation > -width()/8)
    {
        homingAni->setStartValue(m_deviation);
        homingAni->setEndValue(0);
    }
    else if(m_deviation < -width()/8)
    {
        homingAni->setStartValue(-(width()-1)/8-m_deviation);
        homingAni->setEndValue(0);
        m_currentValue++;
    }

    m_currentValue = calculateLoopNum(m_currentValue);

    emit currentValueChanged(m_currentValue);
    homingAni->start();
}

int RollingBox::readDeviation()
{
    return m_deviation;
}

void RollingBox::setDeviation(int n)
{
    m_deviation = n;
    repaint();
}

int RollingBox::calculateLoopNum(int num)
{
    while (num < m_minRange) num += m_rangeSpan;
    while (num > m_maxRange) num -= m_rangeSpan;

    return num;
}

